<?php
namespace org\crawlgenie\application\filter;
use \Logger;
use \CGException;
/**
 *  Filter class adds several static filtering methods
 *  that're used in the application
 *
 *  @author $Author: jinsonxu@gmail.com $:
 *  $Date: 2014-11-09 22:57:19 +0000 (Sun, 09 Nov 2014) $:
 *  $Id: Filter.php 6 2014-11-09 22:57:19Z jinsonxu@gmail.com $:
 *  @version $Rev: 6 $:
 *  @package crawlgenie.application
 *  @subpackage filter
 */


defined('_CGEXEC') or die('Direct access not allowed');

class Filter {


    public static function htmlEncode($data) {
        return htmlentities($data, ENT_QUOTES, 'UTF-8');
    }


    public static function htmlDecode($data) {
        return html_entity_decode($data, ENT_QUOTES, 'UTF-8');
    }



    public static function cleanText(/*string*/$text) {
        $text = preg_replace( '/<script[^>]*>.*?<\/script>/si', '', $text );
        $text = preg_replace( '/<a\s+.*?href="([^"]+)"[^>]*>([^<]+)<\/a>/is', '\2 (\1)', $text );
	$text = preg_replace( '/<!--.+?-->/', '', $text );
	$text = preg_replace( '/{.+?}/', '', $text );
	$text = preg_replace( '/&nbsp;/', ' ', $text );
	$text = preg_replace( '/&amp;/', ' ', $text );
	$text = preg_replace( '/&quot;/', ' ', $text );
	$text = strip_tags( $text );
	$text = htmlspecialchars( $text );
	return $text;
    }


    public static function validEmail(/*string*/$email) {
        $result = (!preg_match('/^[_a-z0-9-]+(\.[_a-z0-9-]+)*@[a-z0-9-]+(\.[a-z0-9-]+)*(\.([a-z]){2,6})$/i',$email)) ? 0 : 1;
        return $result;
    }




    /**
     * Cleans input according to specified type
     * @param	mixed	$source	Input string/array-of-string to be 'cleaned'
     * @param	string	$type	Return type for the variable (INT, FLOAT, BOOLEAN, WORD, ALNUM, CMD, BASE64, STRING, ARRAY, PATH, NONE)
     * @return	mixed	'Cleaned' version of input parameter
     */
    public static function clean($source, $type='string')
    {
    // Handle the type constraint
        switch (strtoupper($type))
        {
            case 'INT' :
            case 'INTEGER' :
                    // Only use the first integer value
                    preg_match('/-?[0-9]+/', (string) $source, $matches);
                    $result = @ (int) $matches[0];
                    break;

            case 'FLOAT' :
            case 'DOUBLE' :
                    // Only use the first floating point value
                    preg_match('/-?[0-9]+(\.[0-9]+)?/', (string) $source, $matches);
                    $result = @ (float) $matches[0];
                    break;

            case 'BOOL' :
            case 'BOOLEAN' :
                    $result = (bool) $source;
                    break;

            case 'WORD' :
                    $result = (string) preg_replace( '/[^A-Z_]/i', '', $source );
                    break;

            case 'ALNUM' :
                    $result = (string) preg_replace( '/[^A-Z0-9]/i', '', $source );
                    break;

            case 'CMD' :
                    $result = (string) preg_replace( '/[^A-Z0-9_\.-]/i', '', $source );
                    $result = ltrim($result, '.');
                    break;

            case 'BASE64' :
                    $result = (string) preg_replace( '/[^A-Z0-9\/+=]/i', '', $source );
                    break;

            case 'STRING' :
			$result = (string) strip_tags(self::_decode((string) $source));
                    break;

            case 'ARRAY' :
                    $result = (array) $source;
                    break;

            case 'PATH' :
                    $pattern = '/^[A-Za-z0-9_-]+[A-Za-z0-9_\.-]*([\\\\\/][A-Za-z0-9_-]+[A-Za-z0-9_\.-]*)*$/';
                    preg_match($pattern, (string) $source, $matches);
                    $result = @ (string) $matches[0];
                    break;

            case 'USERNAME' :
                    $result = (string) preg_replace( '/[\x00-\x1F\x7F<>"\'%&]/', '', $source );
                    break;

            default :
                    // Are we dealing with an array?
                    if (is_array($source)) {
                        foreach ($source as $key => $value)
			{
                            // filter element for XSS and other 'bad' code etc.
                            if (is_string($value)) {
                                $source[$key] = strip_tags(self::_decode($value));
                            }
			}
			$result = $source;
                    } else {
                        // Or a string?
			if (is_string($source) && !empty ($source)) {
                            // filter source for XSS and other 'bad' code etc.
                            $result = strip_tags(self::_decode($source));
			} else {
                            // Not an array or string.. return the passed parameter
                            $result = $source;
			}
                    }
                    break;
            }
        return $result;
    }




    /**
     * Convert to plaintext
     * @param	string	$source
     * @return	string	Plaintext string
     */
    public static function _decode($source)
    {
        // entity decode
	$trans_tbl = get_html_translation_table(HTML_ENTITIES);
	foreach($trans_tbl as $k => $v) {
            $ttr[$v] = utf8_encode($k);
	}
	$source = strtr($source, $ttr);
	// convert decimal
	$source = preg_replace('/&#(\d+);/me', "utf8_encode(chr(\\1))", $source); // decimal notation
	// convert hex
	$source = preg_replace('/&#x([a-f0-9]+);/mei', "utf8_encode(chr(0x\\1))", $source); // hex notation
	return $source;
    }


    /**
     * Decode htmlentities and utf8 for all values
     * in an array
     *
     * @param <type> $data
     */
    public static function decodeArray($data) {
        $result = array();
        $referenceArray = array();

        foreach($data as $key => $value) {
            if(is_array($value)) {
                //recurse
                if(!in_array($value, $referenceArray)) {
                    $result[$key] = self::decodeArray($value);
                    $referenceArray[] = $value;
                }

            } else {
                $result[$key] = utf8_decode(urldecode($value));
            }
        }
        return $result;
    }


    
    public static function encodeArray($data) {
        $result = array();
        $referenceArray = array();

        foreach($data as $key => $value) {
            if(is_array($value)) {
                //recurse
                if(!in_array($value, $referenceArray)) {
                    $result[$key] = self::encodeArray($value);
                    $referenceArray[] = $value;
                }
            } else {
                $result[$key] = utf8_encode($value);
            }
        }
        return $result;
    }




    public static function jsonEncode($data, $asObject = false) {

//        Logger::getLogger(__CLASS__)->info(__METHOD__ . ': Within jsonEncode now, data to encode: ' . print_r(self::decodeArray($data), true));

//        $return = json_encode(self::encodeArray(self::decodeArray($data)));
        $return = ($asObject) ? json_encode($data, JSON_FORCE_OBJECT) : json_encode($data);

//        Logger::getLogger(__CLASS__)->info(__METHOD__ . ': Encoded result: ' . print_r($return, true));

        return $return;
    }


    public static function jsonDecode($data, $asArray = true) {

//        Logger::getLogger(__CLASS__)->info(__METHOD__ . ': Within jsonDecode, data: ' . print_r($data, true));

//        $return = self::decodeArray(json_decode(utf8_encode(utf8_decode($data)), $asArray));
        //
        //by right all json passed via xmlhttprequest is already utf8 encoded
        $return = json_decode($data, $asArray);

//        Logger::getLogger(__CLASS__)->info(__METHOD__ . ': Decoded result: ' . print_r($return, true));
        return $return;
    }


    private static function objectToArray($data) {
        $result = array();
        $references = array();

        // loop over elements/properties
        foreach($data as $key => $value) {
            // recursively convert objects
            if(is_object($value) || is_array($value)) {
                // but prevent cycles
                if(!in_array($value, $references)) {
                    $result[$key] = self::objectToArray($value);
                    $references[] = $value;
                }
            } else {
                // simple values are untouched
                $result[$key] = $value;
            }
        }
        return $result;
    }

}
?>